//********************************************************************************************************
// Product Name: MapWindow.dll Alpha
// Description:  The basic module for MapWindow version 6.0
//********************************************************************************************************
// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); 
// you may not use this file except in compliance with the License. You may obtain a copy of the License at 
// http://www.mozilla.org/MPL/ 
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF 
// ANY KIND, either expressed or implied. See the License for the specificlanguage governing rights and 
// limitations under the License. 
//
// The Original Code is from MapWindow.dll version 6.0
//
// The Initial Developer of this Original Code is Ted Dunsford. Created 6/24/2008 10:48:25 AM
// 
// Contributor(s): (Open source contributors should list themselves and their modifications here). 
//
//********************************************************************************************************

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using MapWindow;
using MapWindow.Main;
using MapWindow.Data;
using MapWindow.Drawing;
using MapWindow.Geometries;

using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX;

namespace MapWindow.DirectX
{


    /// <summary>
    /// LineCapDX
    /// </summary>
    public class ColoredCapListDX : PrimitiveBaseDX
    {
        #region Events


        #endregion

        #region Private Variables

        private int _numSides;
        private int _count;
        private float _width;

        #endregion

        #region Constructors

       
        /// <summary>
        /// Creates a new instance of ColoredCapList using the specified color and line width
        /// </summary>
        /// <param name="color"></param>
        /// <param name="width"></param>
        public ColoredCapListDX(Color color, float width):base(color)
        {
            _numSides = 6;
            _width = width;
        }



        #endregion

        #region Methods

        /// <summary>
        /// Adds a cap to the list
        /// </summary>
        /// <param name="tail">The side of the segment that is not to be capped</param>
        /// <param name="head">The coordinate for the side of the segment to be capped</param>
        public void AddCap(Coordinate tail, Coordinate head)
        {
            double tZ = tail.Z;
            if(double.IsNaN(tZ))tZ = 0.0;
            double hZ = head.Z;
            if(double.IsNaN(hZ))hZ = 0.0;

            Vector vTail = new Vector(tail.X, tail.Y, tZ);
            Vector vHead = new Vector(head.X, head.Y, hZ);

            //Vector3 dir = Vector3.Subtract(vHead, vTail);
            Vector w = Perpendicular(vTail, vHead);
            w = w.Multiply(_width/2);

            Vector start = vHead.Subtract(w);
            Vector end = vHead.Add(w);
            
       
            Vector diff = end.Subtract(start);
            diff = diff.Multiply(.5);
            Vector center = Vector.Add(start, diff);
            Vector z = new Vector(0, 0, -1);
            Vector rot = new Vector(start.Subtract(center));
           


            Vertices.AddCoordinate(center);
            int centerIndex = Vertices.Count - 1;
            Vertices.AddCoordinate(start);
            int prevIndex = Vertices.Count - 1;

            for (int i = 0; i < _numSides; i++)
            {

                Indices.Add(centerIndex);
                Indices.Add(prevIndex);
                rot = rot.RotateZ(-(180 / _numSides));
                Vertices.AddCoordinate(center.Add(rot));
                prevIndex = Vertices.Count - 1;
                Indices.Add(prevIndex);
            }
            _count += 1;
        }

        /// <summary>
        /// Caps are always built clockwise, so a "top" cap would start on the left and end on the right.
        /// </summary>
        /// <param name="start">The starting point for the segment to cap.</param>
        /// <param name="end">The ending point for the segment to cap, cap-side</param>
        public void AddCap(Vector3 start, Vector3 end)
        {
            Vector3 diff = Vector3.Subtract(end, start);
            diff.Multiply(.5F);
            Vector3 center = Vector3.Add(start, diff);
            Vector3 z = new Vector3(0, 0, -1);
            Vector3 rot = Vector3.Subtract(start, center);
          
           
           
            Vertices.AddCoordinate(center);
            int centerIndex = Vertices.Count-1;
            Vertices.AddCoordinate(start);
            int prevIndex = Vertices.Count-1;
        
            for (int i = 0; i < _numSides; i++)
            {
               
                Indices.Add(centerIndex);
                Indices.Add(prevIndex);
                rot.TransformCoordinate(Matrix.RotationZ(Convert.ToSingle(Math.PI / _numSides)));
                Vertices.AddCoordinate(Vector3.Add(center, rot));
                prevIndex = Vertices.Count - 1;
                Indices.Add(prevIndex);
            }
            _count += 1;
        }

        private Vector Perpendicular(Vector start, Vector end)
        {
            Vector up = new Vector(0, 0, 1);
            Vector dir = end.Subtract(start);
            Vector perp = up.Cross(dir);
            perp.Normalize();
            return perp;
        }

        //private Vector3 Perpendicular(Vector3 start, Vector3 end)
        //{
        //    Vector3 up = new Vector3(0, 0, 1);
        //    Vector3 dir = Vector3.Subtract(end, start);
        //    Vector3 perp = Vector3.Cross(up, dir);
        //    perp.Normalize();
        //    return perp;
        //}
       

        

       

        #endregion

        #region Properties

       

        /// <summary>
        /// Gets or sets the integer number of triangles to drawn for each of the end caps.
        /// The default is 6
        /// </summary>
        public int TrianglesPerCap
        {
            get { return _numSides; }
            set { _numSides = value; }
        }

        /// <summary>
        /// Gets the number of caps that have been added
        /// </summary>
        public int Count
        {
            get { return _count; }
            
        }

        
       

     


        #endregion

       



    }
}
